package com.za.plugin.util;

import org.apache.ibatis.annotations.Mapper;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.*;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class DataSourceUtil {

    @Resource
    private ApplicationContext context;


    // 根据 @Mapper 注解获取 Spring 容器的 mapper bean。如果 mapper bean 没有用该注解而是使用 包扫描的方式，
    // 则为每个 mapper 接口手动添加该注解，使用 "TestUtil.addMapper(filePath);" 一键添加
    public List<Object> getAllMapperBean() {
        List<Object> list = new ArrayList<>();
        Map<String, Object> beans = context.getBeansWithAnnotation(Mapper.class);
        for (Map.Entry<String, Object> entry : beans.entrySet()) {
            list.add(entry.getValue());
        }
        list.sort((Comparator.comparing(Object::toString)));
        return list;
    }


    // 获取表的主键名称
    public Set<String> getPKs(String tableName) {
        DataSource dataSource = context.getBean(DataSource.class);
        try (Connection connection = dataSource.getConnection();
             ResultSet rs = connection.getMetaData().getPrimaryKeys(null, null, tableName)) {
            if (null == rs) {
                return Collections.emptySet();
            }
            Set<String> pks = new HashSet<>();
            String pkStr = "*";
            while (rs.next()) {
                pkStr = rs.getString("COLUMN_NAME");
                pks.add(pkStr.toLowerCase());
            }
            return pks;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Collections.emptySet();
    }

    // 获取表的自增列字段名称
    public List<String> getAutoIncrProperties(String tableName) {

        String sql = "select * from " + tableName;  //因为id为自动增长主键

        List<String> autoIncrList = new ArrayList<>();
        // 防止传过来的 tableName 是一个子查询导致 “有参数未绑定: 0” 报错
        if (tableName.contains(" ")) {
            return autoIncrList;
        }
        DataSource dataSource = context.getBean(DataSource.class);
        try (Connection connection = dataSource.getConnection();
             PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
             ResultSet resultSet = ps.executeQuery()) {
            ResultSetMetaData metaData = resultSet.getMetaData();
            for (int i = 1; i <= metaData.getColumnCount(); i++) {
                if (metaData.isAutoIncrement(i)) {
                    autoIncrList.add(metaData.getColumnName(i).toLowerCase());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return autoIncrList;
    }

    // 获取表主键字段并标注该主键字段是否自增，一般只有一个主键字段，但也可能是联合主键
    public Map<String, Boolean> isPkAutoIncrement(String tableName) {
        Set<String> pks = getPKs(tableName);
        pks = pks.stream().map(String::toUpperCase).collect(Collectors.toSet());
        StringBuilder pksStr = new StringBuilder();
        for (String pk : pks) {
            pksStr.append(pk).append(",");
        }
        if (pksStr.length() == 0) {
            pksStr.append("*");
        } else {
            pksStr.deleteCharAt(pksStr.length() - 1);
        }
        String sql = "select " + pksStr.toString() + " from " + tableName;  //因为id为自动增长主键

        Map<String, Boolean> pkAutoIncrMap = new LinkedHashMap<>();
        DataSource dataSource = context.getBean(DataSource.class);
        try (Connection connection = dataSource.getConnection();
             PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
             ResultSet resultSet = ps.executeQuery()) {
            ResultSetMetaData metaData = resultSet.getMetaData();
            for (int i = 1; i <= metaData.getColumnCount(); i++) {
                if (pks.contains(metaData.getColumnName(i))) {
                    if (metaData.isAutoIncrement(i)) {
                        pkAutoIncrMap.put(metaData.getColumnName(i).toLowerCase(), true);
                    } else {
                        pkAutoIncrMap.put(metaData.getColumnName(i).toLowerCase(), false);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return pkAutoIncrMap;
    }

    public Map<String, List<String>> getPkAndUniqueKeys(String tableName) {
        DataSource dataSource = context.getBean(DataSource.class);
        try (Connection conn = dataSource.getConnection()) {
            System.out.println(conn.getMetaData());
            List<Map<String, Object>> columns = null;

            String uniqueIndexQuery = "SELECT a.* from DBA_IND_COLUMNS  a WHERE  TABLE_NAME=?";

            try (PreparedStatement uniqueIndexStmt = conn.prepareStatement(uniqueIndexQuery)) {
                uniqueIndexStmt.setString(1, tableName);
                ResultSet rs = uniqueIndexStmt.executeQuery();
                Map<String, List<String>> map = new HashMap<>();

                while (rs.next()) {
                    String columnName = rs.getString("COLUMN_NAME");
                    String indexName = rs.getString("INDEX_NAME");
                    if (!map.containsKey(indexName)) {
                        map.put(indexName, new ArrayList<>());
                    }
                    map.get(indexName).add(columnName);
                }
                return map;
            } catch (Exception e) {
                e.printStackTrace();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return new HashMap<>();
    }
}

